package cn.edu.xust.service.impl;

import cn.edu.xust.configuration.exception.Default200Exception;
import cn.edu.xust.configuration.exception.ErrorConstant;
import cn.edu.xust.dao.SysMenuDao;
import cn.edu.xust.entity.SysMenuEntity;
import cn.edu.xust.entity.SysMenuprivilegeEntity;
import cn.edu.xust.entity.SysUserEntity;
import cn.edu.xust.entity.SysUserroleEntity;
import cn.edu.xust.Ro.MenuRo;
import cn.edu.xust.Ro.MenuTreeRo;
import cn.edu.xust.service.*;
import cn.edu.xust.util.PageUtils;
import cn.edu.xust.util.Query;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;


@Service("sysMenuService")
public class SysMenuServiceImpl extends ServiceImpl<SysMenuDao, SysMenuEntity> implements SysMenuService {
    @Autowired
    private SysRoleprivilegeService sysRoleprivilegeService;

    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private SysMenuprivilegeService sysMenuprivilegeService;
    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysUserroleService sysUserroleService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SysMenuEntity> page = this.page(
                new Query<SysMenuEntity>().getPage(params),
                new QueryWrapper<SysMenuEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<SysMenuEntity> getByMenuids(List<Integer> menuidsdistinct) {


        QueryWrapper<SysMenuEntity> wap = new QueryWrapper<SysMenuEntity>().in("menuid", menuidsdistinct);

        return baseMapper.selectList(wap);
    }

    @Override
    public MenuRo getrouteByNP(String username, String pwd) throws Default200Exception {


        SysUserEntity user = sysUserService.getByNameAndPwd(username, pwd);
        if (user == null) {
            throw new Default200Exception(ErrorConstant.user_not_exist);
        }

        String utype = user.getUtype();


        //系统管理员 获取所有菜单
        if (utype.equals("-1")) {
            List<SysMenuEntity> allmenus = this.list();
            MenuRo menuRo = convertToAntdRoute(allmenus);
            return menuRo;

        }
        //品牌管理员 获取角色的菜单
        else {
            //查找这个user有哪些role
            List<SysUserroleEntity> sysUserroleEntities = sysUserroleService.getByUid(user.getUid());
            List<Integer> roleids = sysUserroleEntities.stream().map(SysUserroleEntity::getRoleid).collect(Collectors.toList());

            //查找这些role有哪些权限 且 去重pids
            List<Integer> preveids = sysRoleprivilegeService.getByrolesDistinct(roleids);
            if(preveids.size()==0){
                throw new Default200Exception(ErrorConstant.zero_pid);
            }

            //根据pids 反查菜单 这里不用考虑二级菜单还需要反查一级菜单，因为在分配权限菜单的时候，如果分配有二级菜单就会自动分配了对应的一级菜单
            List<SysMenuprivilegeEntity> sysMenuprivilegeEntities = sysMenuprivilegeService.getBypids(preveids);


            //去重menuid
            List<Integer> menuids = sysMenuprivilegeEntities.stream().map(SysMenuprivilegeEntity::getMenuid).collect(Collectors.toList());
            HashSet<Integer> set = new HashSet<>(menuids);
            ArrayList<Integer> menuidsdistinct = new ArrayList<>(set);

            List<SysMenuEntity> menus = this.getByMenuids(menuidsdistinct);
            MenuRo menuRo = convertToAntdRoute(menus);
            return menuRo;

        }
    }

    @Override
    public ArrayList<MenuTreeRo> getTreeMenu(String username, String pwd) throws Default200Exception {


        //验证用户
        SysUserEntity user = sysUserService.getByNameAndPwd(username, pwd);
        if (user == null) {
            throw new Default200Exception(ErrorConstant.user_not_exist);
        }

        String utype = user.getUtype();
        //系统管理员 获取所有菜单
        if (utype.equals("-1")) {
            List<SysMenuEntity> allmenus = this.list();
            List<SysMenuprivilegeEntity> allplist = sysMenuprivilegeService.list();
            return convertToMenuTreeRo2(allmenus, allplist);
        }

        //品牌管理员 获取角色的菜单
        else {

            //查找这个user有哪些role
            List<SysUserroleEntity> sysUserroleEntities = sysUserroleService.getByUid(user.getUid());
            List<Integer> roleids = sysUserroleEntities.stream().map(SysUserroleEntity::getRoleid).collect(Collectors.toList());

            //查找这些role有哪些权限 且 去重pids
            List<Integer> preveids = sysRoleprivilegeService.getByrolesDistinct(roleids);

            //根据pids 反查菜单 这里不用考虑二级菜单还需要反查一级菜单，因为在分配权限菜单的时候，如果分配有二级菜单就会自动分配了对应的一级菜单
            List<SysMenuprivilegeEntity> sysMenuprivilegeEntities = sysMenuprivilegeService.getBypids(preveids);

            //去重menuid
            List<Integer> menuids = sysMenuprivilegeEntities.stream().map(SysMenuprivilegeEntity::getMenuid).collect(Collectors.toList());
            HashSet<Integer> set = new HashSet<>(menuids);
            ArrayList<Integer> menuidsdistinct = new ArrayList<>(set);

            //拿到菜单
            List<SysMenuEntity> menus = this.getByMenuids(menuidsdistinct);

            //转换成tree需要的格式
            ArrayList<MenuTreeRo> menuTreeRos = convertToMenuTreeRo2(menus, sysMenuprivilegeEntities);
            return menuTreeRos;
        }
    }


    //根据菜单组装成antd路由的样子
    public MenuRo convertToAntdRoute(List<SysMenuEntity> allmenus) {

        //组装菜单成前端需要的样子
        CopyOnWriteArrayList<MenuRo> list = new CopyOnWriteArrayList<>();

        List<SysMenuEntity> menu1 = allmenus.stream().filter(item -> item.getMenurank() == 1).collect(Collectors.toList());
        for (SysMenuEntity item : menu1) {
            MenuRo menuRo = new MenuRo();

            //找到一级菜单
            menuRo.setName(item.getCname());
            menuRo.setRouter(item.getRoute());
            menuRo.setSort(item.getSort());

            //找到他的二级菜单
            List<SysMenuEntity> collect = allmenus.stream().filter(item2 ->(item.getMenuid().equals(item2.getFathermid()))).collect(Collectors.toList());

            //一级的孩子=二级菜单数组
            CopyOnWriteArrayList<MenuRo> arrayList = new CopyOnWriteArrayList<>();
            collect.forEach(it -> {
                MenuRo two_menuRo = new MenuRo();
                two_menuRo.setName(it.getCname());
                two_menuRo.setRouter(it.getRoute());
                two_menuRo.setSort(it.getSort());
                //二级菜单数组
                arrayList.add(two_menuRo);
            });
            //添加到一级菜单中
            Collections.sort(arrayList);
            menuRo.setChildren(arrayList);
            list.add(menuRo);
        }
        //添加到root
        MenuRo menuRo = new MenuRo();
        menuRo.setRouter("root");
        Collections.sort(list);
        menuRo.setChildren(list);
        return menuRo;


    }


    //权限转换成MenuTreeRo
    public ArrayList<MenuTreeRo> convertToMenuTreeRo(List<SysMenuprivilegeEntity> sysMenuprivilegeEntities) {


        ArrayList<MenuTreeRo> menuTreeRos = new ArrayList<>();


        for (SysMenuprivilegeEntity sysMenuprivilegeEntity : sysMenuprivilegeEntities) {
            MenuTreeRo menuTreeRo = new MenuTreeRo();
            menuTreeRo.setKey(String.valueOf(sysMenuprivilegeEntity.getPrivilegeid()));
            menuTreeRo.setTitle(sysMenuprivilegeEntity.getPrivilegename());
            menuTreeRo.setChildren(null);
            menuTreeRos.add(menuTreeRo);
        }

        return menuTreeRos;


    }


    //根据提供的权限和菜单 做数据加工
    public ArrayList<MenuTreeRo> convertToMenuTreeRo2(List<SysMenuEntity> allmenus, List<SysMenuprivilegeEntity> allplist) {

        //拿到一级菜单
        List<SysMenuEntity> onemeuns = allmenus.stream().filter(e -> e.getMenurank() == 1).collect(Collectors.toList());

        //拿到2级菜单
        List<SysMenuEntity> twomeuns = allmenus.stream().filter(e -> e.getMenurank() == 2).collect(Collectors.toList());

        ArrayList<MenuTreeRo> menuTreeRos1 = new ArrayList<>();

        //拿着一级菜单对数据做转换
        for (SysMenuEntity onemeun : onemeuns) {

            //容易得到的数据直接set
            MenuTreeRo menuTreeVo = new MenuTreeRo();
            menuTreeVo.setKey("A-" + onemeun.getMenuid());
            menuTreeVo.setTitle(onemeun.getCname());

            //不容易得到的二级菜单
            List<SysMenuEntity> oneOfTwos = twomeuns.stream().filter(e -> e.getFathermid().equals(onemeun.getMenuid())).collect(Collectors.toList());
            ArrayList<MenuTreeRo> menuTreeRos2 = new ArrayList<>();
            //二级菜单有权限，获取每个二级菜单的权限 并转换成ro
            for (SysMenuEntity oneOfTwo : oneOfTwos) {
                MenuTreeRo menuTreeRo = new MenuTreeRo();
                menuTreeRo.setKey("B-" + oneOfTwo.getMenuid());
                menuTreeRo.setTitle(oneOfTwo.getCname());
                List<SysMenuprivilegeEntity> prev = allplist.stream().filter(e -> e.getMenuid().equals(oneOfTwo.getMenuid())).collect(Collectors.toList());
                //权限转换成ro
                ArrayList<MenuTreeRo> menuTreeRos3 = convertToMenuTreeRo(prev);
                menuTreeRo.setChildren(menuTreeRos3);
                menuTreeRos2.add(menuTreeRo);
            }

            //二级放入一级孩子结点
            menuTreeVo.setChildren(menuTreeRos2);
            menuTreeRos1.add(menuTreeVo);
        }
        return menuTreeRos1;
    }


}